#ifndef Box_First
#define Box_First
#ifdef __GNUG__
#pragma interface
#endif

#include "CompVObject.h"

struct rcinfo;
class SplitMover;

//---- Box ---------------------------------------------------------------------

class Box: public CompositeVObject {
public:
	MetaDef(Box);

	Box(int id, const Point &cr, const Point &gap, VObjAlign);
	Box(int id, const Point &cr, const Point &gap, VObjAlign, VObject*, ...);
	Box(int id, const Point &cr, const Point &gap, VObjAlign, SeqCollection*);
	Box(int id, const Point &cr, const Point &gap, VObjAlign, va_list);

	void SetGap(const Point &g);
	Point GetGap();
	void SetAlign(VObjAlign a);
	VObjAlign GetAlign();
	void SetColsRowsSize(const Point &cr);

	Point ColsRowsSize();
	void SetOrigin(Point at);
	void SetExtent(Point e);
	Metric GetMinSize();
	void Resize(rcinfo *rci);
	void CalcResize(int where, Point d, rcinfo *rci, rcinfo *rci2, rcinfo *rci3);
	int FindVObject(VObject*);
	OStream& PrintOn(OStream&);
	IStream& ReadFrom(IStream&);

protected:
friend SplitMover;
	void getGrid(Point &rc, rcinfo*, bool natural= FALSE);
	Metric getMinSize(Point &rc, rcinfo*, bool natural= FALSE);
	void expand(Point &rc, rcinfo *rci, Point &g, Point &r);

protected:
	Point gap;
	VObjAlign align;
private:
	Point colsrows;
};

inline Point Box::GetGap()
	{ return gap; }

inline VObjAlign Box::GetAlign()
	{ return align; }

//---- HBox --------------------------------------------------------------------

class HBox: public Box {
public:
	MetaDef(HBox);
	HBox(const Point &gap, VObjAlign);
	HBox(const Point &gap, VObjAlign, VObject*, ...);
	HBox(const Point &gap, VObjAlign, SeqCollection*);
	HBox(VObject*, ...);
};

//---- VBox --------------------------------------------------------------------

class VBox: public Box {
public:
	MetaDef(VBox);
	VBox(const Point &gap, VObjAlign);
	VBox(const Point &gap, VObjAlign, VObject*, ...);
	VBox(const Point &gap, VObjAlign, SeqCollection*);
	VBox(VObject*, ...);
};

//---- VObjectPair -------------------------------------------------------------

class VObjectPair: public HBox {
public:
	MetaDef(VObjectPair);
	VObjectPair(VObject *left, VObject *right, const Point &gap= gPoint2);
};

//---- Expander ----------------------------------------------------------------

class Expander: public Box {
public:
	MetaDef(Expander);
	Expander(int id, Direction d, const Point &g);
	Expander(int id, Direction d, const Point &g, VObject *vop, ...);
	Expander(int id, Direction d, const Point &g, SeqCollection *c);
protected:
	void Init(Direction d);
};

class HExpander : public Expander {
public:
	HExpander(const Point &gap, VObject *vop, ...);
};

class VExpander : public Expander {
public:
	VExpander(const Point &gap, VObject *vop, ...);
};

//---- Cluster -----------------------------------------------------------------

class Cluster: public Box {
public:
	MetaDef(Cluster);

	Cluster(int id, VObjAlign a= eVObjVBase, const Point &g= gPoint0);
	Cluster(int id, VObjAlign a, const Point &g, SeqCollection *cp);
	Cluster(int id, VObjAlign a, const Point &g, VObject *,...);
	Cluster(int id, VObjAlign a, const Point &g, va_list);
protected:
	void Init();
};

//---- ManyOfCluster -----------------------------------------------------------

class ManyOfCluster: public Cluster {
public:
	MetaDef(ManyOfCluster);
	ManyOfCluster(int id= cIdNone, VObjAlign a= eVObjHLeft,
			const Point &g= gPoint0, SeqCollection *cp= 0);
	ManyOfCluster(int id, VObjAlign a, const Point &g, char *, ...);
	ManyOfCluster(int id, VObjAlign a, const Point &g, VObject *, ...);
	ManyOfCluster(int id, char *, ...);
	ManyOfCluster(int id, VObject *, ...);
	void Control(int id, int part, void *v);

	void SetItem(int id, bool state);
	void SetItemOn(int i)
		{ SetItem(i, TRUE); }
	void SetItemOff(int i)
		{ SetItem(i, FALSE); }

	void SetAllItems(bool state);
	void SetAllItemsOn()
		{ SetAllItems(TRUE); }
	void SetAllItemsOff()
		{ SetAllItems(FALSE); }

	bool IsItemOn(int id);
};

//---- OneOfCluster ------------------------------------------------------------

class OneOfCluster: public Cluster {
public:
	MetaDef(OneOfCluster);
	OneOfCluster(int id= cIdNone, VObjAlign a= eVObjHLeft,
				const Point &g= gPoint0, SeqCollection *cp= 0);
	OneOfCluster(int id, VObjAlign a, const Point &g, VObject*, ...);
	OneOfCluster(int id, VObjAlign a, const Point &g, char *, ...);
	OneOfCluster(int id, VObject*, ...);
	OneOfCluster(int id, char *, ...);

	void SetValue(int id);
	int GetValue();
	void Control(int id, int part, void *v);

	// obsolete
	void SetItemOn(int i)
		{ SetValue(i); }
	int GetCurrentItem()
		{ return GetValue(); }
};

//---- SplitHandle -------------------------------------------------------------

class SplitHandle : public VObject {
public:
	MetaDef(SplitHandle);
	SplitHandle();
	void Draw(Rectangle r);
	Metric GetMinSize();
	Command *DoLeftButtonDownCommand(Point lp, Token, int);
};

//---- Form --------------------------------------------------------------------

class Form: public Box {
public:
	MetaDef(Form);

	Form(int id, VObjAlign a= eVObjHCenter, const Point &g= gPoint2);
	Form(int id, VObjAlign a, const Point &g, SeqCollection *cp);
	Form(int id, VObjAlign a, const Point &g, VObject*, ...);
	Form(int id, VObjAlign a, const Point &g, char*, ...);
	Form(VObject*, ...);
	Form(char*, ...);

protected:
	void Init(char *label, va_list ap);
	void SetContainer(VObject*);
};

#endif

